
#include "nalu/SeqParamSet.h"
#include "nalu/bit_reader.h"

#include <QDebug>


CSeqParamSet::CSeqParamSet(const uint8_t* data, uint32_t size)
    : m_data(data)
    ,m_size(size)
    ,m_height(0)
    ,m_width(0)
{
    memset(&sps, 0, sizeof(seq_parameter_set_rbsp));

    bit_reader *bits = new bit_reader(m_data, m_size);

    /* skip first byte, since we already know we're parsing a SPS */
    //67 or 68
    bits->skip(8);


    //H.264编码体系定义了4种不同的Profile(类)：(其实就是画质的不同)
    //Baseline Profile(基线类)
    /*
         *提供I/P帧，仅支持progressive(逐行扫描)和CAVLC
         *
         */

    //Main Profile(主要类)
    /*
         * 提供I/P/B帧，支持progressive(逐行扫描)和interlaced(隔行扫描)，提供CAVLC或CABAC
         */


    //Extended Profile(扩展类)
    /*
         * 提供I/P/B/SP/SI帧，仅支持progressive(逐行扫描)和CAVLC
         */


    //High Profile(高端类)
    /*
         *也就是FRExt）在Main Profile基础上新增：
                8x8 intra prediction(8x8 帧内预测),
                custom quant(自定义量化),
                lossless video coding(无损视频编码), 更多的yuv格式（4:4:4...）/
         *
         * */
    /*
         profile 值取值
        Options:
        66  Baseline
            77  Main
        88  Extended
        100  High (FRExt)
        110  High 10 (FRExt)
        122  High 4:2:2 (FRExt)
        144  High 4:4:4 (FRExt)
        */
    sps.profile_idc = bits->read_bits(8);
    printf("profile  idc= %u\n", sps.profile_idc);



    delete bits;

}
CSeqParamSet::CSeqParamSet(std::vector<uint8_t>& data)
    : m_data(data.data())
    ,m_size(data.size())
    ,m_height(0)
    ,m_width(0)
{
    memset(&sps, 0, sizeof(seq_parameter_set_rbsp));


    bit_reader *bits = new bit_reader(m_data, m_size);

    /* skip first byte, since we already know we're parsing a SPS */
    //67 or 68
    bits->skip(8);

    /* get profile idc */
    sps.profile_idc = bits->read_bits(8);
    printf("profile  idc= %u\n", sps.profile_idc);

    // constrained 遵循基线profile(Baseline profile)的所有约束
    sps.constrained_set0_flag = bits->read_bit();
    sps.constrained_set1_flag = bits->read_bit();
    sps.constrained_set2_flag = bits->read_bit();
    sps.constrained_set3_flag = bits->read_bit();
    sps.constrained_set4_flag = bits->read_bit();
    sps.constrained_set5_flag = bits->read_bit();

    sps.reserved_zero_2bits =  bits->read_bits(2);


    //level idc 8位 level 级别 见三种图
    /*
    options:
    10           1 (supports only QCIF format and below with 380160 samples/sec)
    11         1.1 (CIF and below. 768000 samples/sec)
    12         1.2 (CIF and below. 1536000 samples/sec)
    13         1.3 (CIF and below. 3041280 samples/sec)
    20           2 (CIF and below. 3041280 samples/sec)
    21         2.1 (Supports HHR formats. Enables Interlace support. 5068800 samples/sec)
    22         2.2 (Supports SD/4CIF formats. Enables Interlace support. 5184000 samples/sec)
    30           3 (Supports SD/4CIF formats. Enables Interlace support. 10368000 samples/sec)
    31         3.1(Supports 720p HD format. Enables Interlace support. 27648000 samples/sec)
    32         3.2(Supports SXGA format. Enables Interlace support. 55296000 samples/sec)
    40           4(Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
    41         4.1(Supports 2Kx1K format. Enables Interlace support. 62914560 samples/sec)
    42         4.2(Supports 2Kx1K format. Frame coding only. 125829120 samples/sec)
    50           5(Supports 3672x1536 format. Frame coding only. 150994944 samples/sec)
    51         5.1(Supports 4096x2304 format. Frame coding only. 251658240 samples/sec)
    */
    sps.level_idc = bits->read_bits(8);
    printf("level_idc= %u\n", sps.level_idc);

    //指定了由图像参数集指明的序列参数集.
    //seq_parameter_set_id值应该是从0到31，包括0和31
    //注意：当可用的情况下，编码器应该在sps值不同的情况下使用不同的seq_parameter_set_id值，
    //而不是变化某一特定值的seq_parameter_set_id的参数集的语法结构中的值

    sps.seq_parameter_set_id = bits->read_unsigned_exponential_golomb_code();
    printf("seq_parameter_set_id= %u\n", sps.seq_parameter_set_id);


    if (sps.profile_idc == 44 || sps.profile_idc == 83 ||
            sps.profile_idc == 86 || sps.profile_idc == 100 ||
            sps.profile_idc == 110 || sps.profile_idc == 118 ||
            sps.profile_idc == 122 || sps.profile_idc == 128 ||
            sps.profile_idc == 134 || sps.profile_idc == 138 ||
            sps.profile_idc == 139 || sps.profile_idc == 244)
    {
        //chroma_format_idc 取值是0 ~ 3，表示的色度采样结构
        //chroma_format_idc 色彩格式
        //0                 单色
        //1                4:2:0
        //2                4:2:2
        //3                4:4:4
        sps.chroma_format_idc = bits->read_unsigned_exponential_golomb_code();
        if (sps.chroma_format_idc == 3)
        {
            sps.separate_colour_plane_flag = bits->read_bit();
        }

        sps.bit_depth_luma_minus8 =
                bits->read_unsigned_exponential_golomb_code() + 8;
        sps.bit_depth_chroma_minus8 =
                bits->read_unsigned_exponential_golomb_code() + 8;
        sps.qpprime_y_zero_transform_bypass_flag = bits->read_bit();


        sps.seq_scaling_matrix_present_flag = bits->read_bit();

        if (sps.seq_scaling_matrix_present_flag)
        {
            uint8_t seq_scaling_matrix_size =
                    ((sps.chroma_format_idc != 3) ? 8 : 12);
            for (uint8_t i = 0; i < seq_scaling_matrix_size; ++i)
            {
                sps.seq_scaling_list_present_flag = bits->read_bit();
                if (sps.seq_scaling_list_present_flag)
                {
                    uint8_t size_of_scaling_list = (i < 6) ? 16 : 64;
                    int64_t last_scale = 8;
                    int64_t next_scale = 8;
                    for (uint8_t j = 0; j < size_of_scaling_list; ++j)
                    {
                        if (next_scale != 0)
                        {
                            auto delta_scale =
                                    bits->read_signed_exponential_golomb_code();
                            next_scale =
                                    (last_scale + delta_scale + 256) % 256;
                        }
                        last_scale =
                                (next_scale == 0) ? last_scale : next_scale;
                    }
                }
            }
        }
    }

    sps.log2_max_frame_num_minus4 = bits->read_unsigned_exponential_golomb_code() + 4;
    sps.pic_order_cnt_type = bits->read_unsigned_exponential_golomb_code();

    if (sps.pic_order_cnt_type == 0)
    {
        sps.log2_max_pic_order_cnt_lsb_minus4 =bits->read_unsigned_exponential_golomb_code() + 4;
    }
    else if (sps.pic_order_cnt_type == 1)
    {
        sps.delta_pic_order_always_zero_flag = bits->read_bit();
        sps.offset_for_non_ref_pic = bits->read_bit();
        sps.offset_for_top_to_bottom_field = bits->read_bit();
        sps.num_ref_frames_in_pic_order_cnt_cycle =bits->read_unsigned_exponential_golomb_code();
        for (uint32_t i = 0;i < sps.num_ref_frames_in_pic_order_cnt_cycle; i++)
        {
            // offset_for_ref_frame[i]
            bits->read_signed_exponential_golomb_code();
        }
    }

    sps.num_ref_frames = bits->read_unsigned_exponential_golomb_code();
    sps.gaps_in_frame_num_value_allowed_flag = bits->read_bit();

    sps.pic_width_in_mbs_minus1 =bits->read_unsigned_exponential_golomb_code() + 1;

    sps.pic_height_in_map_units_minus1 =bits->read_unsigned_exponential_golomb_code() + 1;

    sps.frame_mbs_only_flag = bits->read_bit();

    if (!sps.frame_mbs_only_flag)
    {
        sps.mb_adaptive_frame_field_flag = bits->read_bit();
    }

    sps.direct_8x8_inference_flag = bits->read_bit();
    sps.frame_cropping_flag = bits->read_bit();

    if (sps.frame_cropping_flag)
    {
        sps.frame_crop_left_offset =bits->read_unsigned_exponential_golomb_code();
        sps.frame_crop_right_offset =bits->read_unsigned_exponential_golomb_code();
        sps.frame_crop_top_offset =bits->read_unsigned_exponential_golomb_code();
        sps.frame_crop_bottom_offset =bits->read_unsigned_exponential_golomb_code();
    }

    sps.vui_parameters_present_flag = bits->read_bit();

    uint32_t pic_width_in_samples = sps.pic_width_in_mbs_minus1 * 16;
    m_width = pic_width_in_samples -
            (sps.frame_crop_left_offset * 2) -
            (sps.frame_crop_right_offset * 2);

    // height of each decoded picture in units of macroblocks
    uint32_t pic_height_in_mbs =
            sps.pic_height_in_map_units_minus1 * (2 - sps.frame_mbs_only_flag);

    uint32_t pic_height_in_samples = pic_height_in_mbs * 16;

    m_height =pic_height_in_samples -
            (sps.frame_crop_top_offset * 2) -
            (sps.frame_crop_bottom_offset * 2);

    qDebug() << "m_width :" <<m_width <<" m_height:" <<m_height;


    delete bits;

}



CSeqParamSet::~CSeqParamSet()
{
}

